// TODO: CODE REVIEW & CLEANUP!
//
// TouchMessageBox.cs
//
// Implements TouchMessageBox and related types.
//

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using HomeUX.ClientControlSupport;

namespace HomeUX.Controls
{

[TemplatePart(Name = LayoutRootName, Type = typeof(Panel))]
[TemplatePart(Name = MessageTextBlockName, Type = typeof(TextBlock))]
[TemplatePart(Name = ButtonPanelName, Type = typeof(Panel))]
[TemplatePart(Name = Button0Name, Type = typeof(ButtonBase))]
[TemplatePart(Name = Button1Name, Type = typeof(ButtonBase))]
[TemplatePart(Name = Button2Name, Type = typeof(ButtonBase))]
[TemplatePart(Name = Button3Name, Type = typeof(ButtonBase))]
[TemplatePart(Name = Button4Name, Type = typeof(ButtonBase))]
public class TouchMessageBox : Control, IControlHelperConnector
{
    public const string LayoutRootName = "LayoutRoot";
    public const string MessageTextBlockName = "Message";
    public const string ButtonPanelName = "ButtonPanel";
    public const string Button0Name = "Button0";
    public const string Button1Name = "Button1";
    public const string Button2Name = "Button2";
    public const string Button3Name = "Button3";
    public const string Button4Name = "Button4";

    string _buttonLabels;
    Panel _layoutRoot;
    TextBlock _messageTextBlock;
    Panel _buttonPanel;
    ButtonBase[] _buttons = new ButtonBase[5];
    int _clickedButtonIndex = -1;
	DialogSettings _settings;

    public static readonly DependencyProperty MessageProperty =
        DependencyProperty.Register("Message", typeof(string), typeof(TouchMessageBox), null);
            //new PropertyMetadata(OnMessagePropertyChanged));

    //static void OnMessagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    //{
    //    var target = (TouchMessageBox)d;
    //}

    public string Message
    {
        get
        {
            return (string)GetValue(MessageProperty);
        }
        set
        {
            SetValue(MessageProperty, value);
        }
    }

    public bool HasButtons { get; private set; }

    public void Close(bool restorePreviousFocus)
    {
        ClientUtil.CloseDialog(this, restorePreviousFocus);
    }

    // note: <buttonLabels> can be null, to display a message without buttons
    public static TouchMessageBox Show(FrameworkElement parent, string message, string buttonLabels, Action<int> onClose)
	{
		return Show(parent, message, buttonLabels, onClose, new DialogSettings());
	}

    public static TouchMessageBox Show(FrameworkElement parent, string message, string buttonLabels, Action<int> onClose, DialogSettings settings)
    {
        var dialog = new TouchMessageBox();
        dialog.Message = message;
        dialog._buttonLabels = buttonLabels;
        dialog._settings = settings;

        settings.OnClose = delegate()
            {
                if (onClose != null)
                    onClose(dialog._clickedButtonIndex);
            };

        ClientUtil.ShowDialog(parent, dialog, settings);
        return dialog;
    }

    public TouchMessageBox()
    {
        DefaultStyleKey = typeof(TouchMessageBox);
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        ControlHelper.GetRequiredTemplateChild(this, LayoutRootName, out _layoutRoot);
        ControlHelper.GetRequiredTemplateChild(this, MessageTextBlockName, out _messageTextBlock);
        ControlHelper.GetRequiredTemplateChild(this, ButtonPanelName, out _buttonPanel);
        ControlHelper.GetRequiredTemplateChild(this, Button0Name, out _buttons[0]);
        ControlHelper.GetRequiredTemplateChild(this, Button1Name, out _buttons[1]);
        ControlHelper.GetRequiredTemplateChild(this, Button2Name, out _buttons[2]);
        ControlHelper.GetRequiredTemplateChild(this, Button3Name, out _buttons[3]);
        ControlHelper.GetRequiredTemplateChild(this, Button4Name, out _buttons[4]);

        _layoutRoot.MouseLeftButtonDown += _layoutRoot_MouseLeftButtonDown;

        //_layoutRoot.KeyDown += new System.Windows.Input.KeyEventHandler(LayoutRoot_KeyDown);

        //_messageTextBlock.Text = Message;


        //_buttons[0].Width = double.NaN;


        int buttonIndex = 0;
        foreach (ButtonBase button in _buttons)
        {
            button.Click += Button_Click;
            button.Tag = buttonIndex;
            button.MinWidth = button.Width;
            button.Width = double.NaN;
            buttonIndex++;
        }

        if (_buttonLabels != null)
        {
            _buttonPanel.Visibility = Visibility.Visible;
            buttonIndex = 0;
            foreach (string buttonLabel in _buttonLabels.Split('|'))
            {
                if (buttonIndex < _buttons.Length)
                {
                    ButtonBase button = _buttons[buttonIndex];
                    button.Content = buttonLabel;
                    button.Visibility = Visibility.Visible;
                    HasButtons = true;
                }
                buttonIndex++;
            }
        }
        else
        {
            _buttonPanel.Visibility = Visibility.Collapsed;
        }

        //Dispatcher.BeginInvoke(() => _buttons[0].Focus());
    }

    void _layoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // if the message box has no buttons and isn't modal, clicking on it dismisses it
        if (!HasButtons && !_settings.IsModal)
            ClientUtil.CloseDialog(this, true);
    }

#if false
    void LayoutRoot_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Escape)
        {
            e.Handled = true;
            CloseDialog(-1);
        }
    }
#endif

    void Button_Click(object sender, RoutedEventArgs e)
    {
        var button = (ButtonBase) sender;
        _clickedButtonIndex = (int)button.Tag;
        ClientUtil.CloseDialog(this, true);
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        _messageTextBlock.MinWidth = availableSize.Width / 3;
        Size size = base.MeasureOverride(availableSize);

        double maxWidth = _messageTextBlock.DesiredSize.Width;
        double minWidth = Math.Min(maxWidth, availableSize.Width / 2);
        const int stepCount = 10;
        double deltaWidth = (maxWidth - minWidth) / stepCount;

        double desiredAspectRatio = availableSize.Width / availableSize.Height;

        _messageTextBlock.Width = maxWidth;
        double bestAspectRatio = size.Width / size.Height;
        double bestTextWidth = maxWidth;
        for (int step = 0; step < stepCount; step++)
        {
            _messageTextBlock.Width -= deltaWidth;
            size = base.MeasureOverride(availableSize);
            double aspectRatio = size.Width / size.Height;
            if (Math.Abs(bestAspectRatio - desiredAspectRatio) > Math.Abs(aspectRatio - desiredAspectRatio))
            {
                bestAspectRatio = aspectRatio;
                bestTextWidth = _messageTextBlock.Width;
            }

        }

        if (_buttonLabels == null)
        {
            // special case: if there are no buttons and the text displays in a single line, avoid
            // white space on the right (it looks weird) -- we test this by seeing if the "natural
            // width" of the text block would be less than <bestTextWidth>, and, if so, we let the
            // "natural width" prevail
            _messageTextBlock.MinWidth = 0;
            _messageTextBlock.Width = double.NaN;
            _messageTextBlock.Measure(new Size(32767, 32767));
            if (_messageTextBlock.DesiredSize.Width > bestTextWidth)
                _messageTextBlock.Width = bestTextWidth;
        }
        else
            _messageTextBlock.Width = bestTextWidth;

        return base.MeasureOverride(availableSize);
    }

#if false
    protected override Size ArrangeOverride(Size finalSize)
    {
        Size size = base.ArrangeOverride(finalSize);

        return size;
    }
#endif

    Control IControlHelperConnector.GetControl()
    {
        return this;
    }

    DependencyObject IControlHelperConnector.GetTemplateChild(string childName)
    {
        return GetTemplateChild(childName);
    }
}

}

